`timescale 10ns / 100ps
/*
 Автор: Швейкин Евгений Юрьевич
 Функциональное описание:
        Модуль целочисленного деления.
        Деление выполняется в столбик и занимает количество тактов равное числу разрядов +2.
        Запуск деления выполняется по заднему фронту сигнала req, значения числителя и знаменателя 
        на входе могут быть изменены после снятия сигнала req.
        На выходе модуля результат деления является действительным только при установленном 
    сигнале valid
*/
                       
module mod_divide
    #(  parameter integer dw_p = 16     // Разрядность данных
    )
    (   input logic                     reset,
        input logic                     clk,
        input logic                     req,
        input logic [dw_p - 1:0]        numer,
        input logic [dw_p - 1:0]        denom,
        
        output logic [dw_p - 1:0]       quotient,
        output logic [dw_p - 1:0]       remain,
        output logic                    valid
        );
//*********************** КОНСТАНТЫ ****************************************************************

//*********************** СОЗДАНИЕ И ОПИСАНИЕ ПЕРЕМЕННЫХ *******************************************
    integer             cnt;
    logic [dw_p - 1:0]  div;
    logic [dw_p - 1:0]  denom_latch;
//********************** БЛОК НЕПРЕРЫВНЫХ НАЗНАЧЕНИЙ ASSIGN ****************************************
  
    always_ff @(posedge clk, posedge reset)
    begin
        if (reset) begin
            valid   <= 1'b0;            // После ресета валидного результата деления нет 
            cnt     <= dw_p + 1;        // и счетчик в исходное состояние
        end
        else begin
            if (req) begin                      // Пришел сигнал на запрос деления
                div         <= numer;           // число с шины кидаем в делимое
                cnt         <= dw_p + 1;        // Счетчик разрядов
                quotient    <= {dw_p{1'b0}};    // частное пока = 0
                remain      <= {dw_p{1'b0}};    // Остаток =0
                valid       <= 1'b0;            // Деление не закончено
                denom_latch <= denom;           // Защелкиваем значение делителя
                
            end
            else begin
                if (cnt > 0) begin;     // Будем долбиться пока не пройдем все разряды
                    div <= div << 1;    // На каждом такте будем двигать делимое влево на 1 такт
                                        // в этом случае через старший разряд пройдут все биты числа
                    // Делаем проверку. Если текущий остаток >= делителя, то
                    if (remain >= denom_latch) begin
                        // Частное +1 и сдвигаем на 1 разяряд влево
                        quotient    <= (quotient << 1) + {{(dw_p - 1){1'b0}}, 1'b1};
                        // Из остатка вычитаем делитель, разность двигаем на 1 разряд и в младший 
                        // разряд добавляем старший разряд текущего делимого
                        if (cnt != 1)
                            remain     <= ((remain - denom_latch) << 1) + div[dw_p - 1];
                        else
                            remain     <= (remain - denom_latch);
                    end
                    else begin
                        // Если остаток < делителя, то сдвигаем и добавляем старший разряд делимого
                        if (cnt != 1)
                            remain  <= (remain << 1) + div[dw_p - 1];    
                        else;
                        // Частное только сдвигаем
                        quotient    <= quotient << 1;
                    end
                    cnt <= cnt - 1;  // Декремент счетчика
                end
                else begin
                    // Когда чсетчик будет равен 0, поставим валид, значит вычисление завершено
                    valid <= 1'b1;    
                end
            end
        end
    end    
        
endmodule